home *** CD-ROM | disk | FTP | other *** search
- /* National Institute of Standards and Technology (NIST)
- /* National Computer System Laboratory (NCSL)
- /* Office Systems Engineering (OSE) Group
- /* ********************************************************************
- /* D I S C L A I M E R
- /* (March 8, 1989)
- /*
- /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
- /* NCSL OSE SGML parser validation suite. If the SGML parser and/or
- /* validation suite is modified by someone else and passed on, NIST wants
- /* the parser's recipients to know that what they have is not what NIST
- /* distributed, so that any problems introduced by others will not
- /* reflect on our reputation.
- /*
- /* Policies
- /*
- /* 1. Anyone may copy and distribute verbatim copies of the SGML source
- /* code as received in any medium.
- /*
- /* 2. Anyone may modify your copy or copies of SGML parser source code or
- /* any portion of it, and copy and distribute such modifications provided
- /* that all modifications are clearly associated with the entity that
- /* performs the modifications.
- /*
- /* NO WARRANTY
- /* ===========
- /*
- /* NIST PROVIDES ABSOLUTELY NO WARRANTY. THE SGML PARSER AND VALIDATION
- /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
- /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
- /* WITH YOU. SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
- /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
- /*
- /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
- /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
- /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
- /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
- /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
- /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
- /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
- */
-
- /************************************************************************/
- /* TITLE: SGML PARSER */
- /* SYSTEM: DTD PROCESSOR */
- /* SUBSYSTEM: */
- /* SOURCE FILE: DETERMIN.C */
- /* AUTHOR: Michael Garris */
- /* */
- /* DATE CREATED: */
- /************************************************************************/
- #include <stdio.h>
- #include "detdefs.h"
- #include "detglbl.h"
- /**************************/
- /* MAIN (to be removed) ***/
- /**************************/
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char eltname[128];
- FILE *infile;
- char inrec[2048];
- int j, c, error = 0;
-
- if ((infile = fopen("cmfile.sgm", "r")) == NULL){
- printf("unable to open cmfile.sgm \n");
- exit(1);
- }
- while(fgets(eltname, sizeof(eltname), infile) != NULL){
- fgets(inrec, sizeof(inrec), infile);
- for(j = 0; j < sizeof(inrec); j++){
- if (inrec[j] < ' ') {
- inrec[j] = '\0';
- break;
- }
- }
- if (determin(inrec) == TRUE) {
- error = 1;
- printf("For element %s:", eltname);
- printf("the content model:\n%s\n", inrec);
- printf("is SUSPICIOUS and/or AMBIGUOUS\n");
- }
- }
- fclose(infile);
- /*(void) unlink(fname);*/
- if (error != 0) {
- printf("\n\nSuspicious and/or ambiguous content models were found\n");
- printf("in this document - do you want to continue (Y/N)? ");
- fflush(stdout);
- c = getchar();
- printf("\n");
- if ((c == 'y') || (c == 'Y'))
- exit(0);
- exit(1);
- }
- exit(0);
- }
-
-
- /******************************/
- /* DETERMIN *******************/
- /* takes pointer to a string */
- /******************************/
- int determin(expr)
- char expr[];
- {
- STATEID *stateid; /* structure of start state pointer and */
- /* final state pointer */
- /* Preprocess the string. First by reducing the content model
- to its simplest form. Second by tokenizing the content model
- for use in determining validity of it. */
- preproc(expr,buffer); /* buffsize is the length of buffer */
- ambmodel = FALSE; /* assume valid */
-
- /* "endbuf" will point to the end of the expression in the buffer */
- /* must send "buffer + 1" to avoid looking at the opening GRPO */
-
- endbuf = findendofgrp(buffer+1,1);
-
- /* invokes function to build FSA from expression in buffer */
- /* on return, stateid will point to the FSA's start state */
- /* final state */
-
- stateid = proclowgrp(buffer,tokseen);
-
- /* invokes procedure to traverse entire FSA listing states visited */
- procinordr(stateid->startptr,stateid->finalptr);
-
- /* invokes procedure which traverses FSA checking for non-determinism */
-
- procdet(stateid->startptr ,stateid->finalptr);
- free((char *)stateid); /* will free last stateid */
- freeFSA(); /* will free linked list of dynamically allocated memory */
- head = NULL;
-
- return(ambmodel);
- if (ambmodel == FALSE)
- printf("Content Model is not ambiguous\n");
- else
- printf("AMBIGUOUS Content Model\n");
- }
- /************************************************************************/
- /************************************************************************/
- /* PROCLOWGRP takes an expression in "buffer" and produces an equivalent*/
- /* FSA using a constructive algorithm. */
- /************************************************************************/
- STATEID *proclowgrp(buffer,tokseen)
- ITEM *buffer;/* contains expression */
- ITEM *tokseen;/*contains tokens already FSAtokened */
- {
- int nest;/* current level of nested parens */
- ITEM *iptr = buffer;/* pointer to expression in buffer */
- STATEID *stateid;/* points to start and final state of */
- /* 'intermediate' FSA */
- ITEM *tokptr = tokseen;/*pointer to end of token seen list */
-
- /* while 'subgroups' remain in expression... */
- while((nest = nestlevel(iptr)) != 0){
- /* invokes procedure to point to lowest-level, leftmost, subgroup */
- getlowgrp(&iptr,nest);
- /* invokes procedure to process each (token,occurance indicator) */
- /* pair in the current subgroup, replacing them by a pointer to an */
- /* equivalent 'intermediate' FSAid */
- tokensingrp(iptr,tokseen,&tokptr);
- /* invokes procedure to process all FSA pointers and connectors in */
- /* the current subgroup, replacing the entire subgroup by a pointer*/
- /* to a more complex intermediate FSAid */
- lowgrp(iptr, nest);
- /* reset pointer to beginning of expression in buffer and repeat the */
- /* above process */
- iptr = buffer;
- }
- /* if, once above loop is exited, the expression pointer does not point */
- /* to a FSAid, then an error in the constructive algorithm has occurred */
- if(iptr++->itoken != POINTER)
- myexit(1,"FSA pointer id not found");
- /* if constructive algorithm has completed normally, then only one FSAid*/
- /* pointer remains in the expression. */
- stateid = iptr->ptoken;
- /* return the pointer to the 'ultimate' FSAid for the*/
- /* inputted expression*/
- return(stateid);
- }
- /************************************************************************/
- /************************************************************************/
- /* TOKENSINGRP takes all (token,occurace indicator) pairs in a subgroup */
- /* and builds an equivalent FSA representing each, replacing each pair */
- /* with a FSAid pointer which points to the corresponding FSA. */
- /************************************************************************/
- void tokensingrp(iptr,tokseen,ptrin)
- ITEM *iptr;/* points to a token within subgroup in expression */
- ITEM *tokseen;/* points to head of token seen list */
- ITEM **ptrin;/* points to next location available in token seen list */
- {
- int token, occind;
- register int connector;
- STATEID *FSAtokid;/* FSAid pointing to the start and final */
- /* state of the FSA equivalent to a */
- /* (token,occurance indicator) pair */
- register ITEM *tokptr = *ptrin;
- int inst;/* instance of token in token seen list */
-
- /* while not end of current subgroup... */
- while((connector = iptr++->itoken) != GRPC){
- /* skip connector, in first pass connector = GRPO */
- /* if pointing to a FSAid pointer within subgroup, skip it */
- /* because it has already been "FSAtokened" */
- if(iptr->itoken == POINTER){
- /* commented out by Michael D. Garris on 11/23/87 */
- /* due to the introduction of ITEM type */
- /* invoke procedure to skip the pointer */
- /* skippointer(&iptr); */
- iptr += 2;
- /* now continue and skip next connector */
- continue;
- }
- /* invoke function to get current token from subgroup */
- /* and strip the location where the token was from the subgroup */
- token = gettoken(iptr);
- /* add new token to token seen list */
- if (tokptr >= (tokseen + BUFFSIZE)) {
- printf("overflow (tokptr) in proclowgrp()\n");
- exit(0);
- }
- tokptr++->itoken = token;
- /* search list to determine instances of token in token seen list */
- inst = searchtoken(token,tokseen,tokptr);
- /* invoke function to get current occurance indicator from subgoup */
- /* and strip the location where the indicator was from the subgroup*/
- occind = getoccind(iptr);
- /* invoke function which takes a (token,occurance indicator) pair */
- /* and build an equivalent FSA, returning the FSAid pointer */
- /* pointing to the start and final state of the newly built FSA */
- FSAtokid = FSAtoken(token,inst,occind);
- /* invoke procedure which inserts the FSAid pointer into the */
- /* subgoup at the location where the most recently stripped */
- /* token and occurance indicator had been */
- insertpointer(&iptr,FSAtokid);
- }
- /* return from procedure after all (token,occurance indicator) pairs */
- /* have been "FSAtokened" */
- *ptrin = tokptr;
- }
- /************************************************************************/
- /************************************************************************/
- /* FSATOKEN inputs a (token,occurance indicator) pair and builds an */
- /* builds an equivalent FSA, returning a FSAid pointer which points */
- /* to the start and final state of the newly built FSA */
- /************************************************************************/
- STATEID *FSAtoken(token,inst,occind)
- int token,inst,occind;
- {
- STATE *start,*final;/* pointers to the start state */
- /* and final state of the FSA to be built */
- STATEID *startid;/* FSAid of FSA to be built */
-
- /* invokes function which allocates memory for a start state */
- start = buildstate();
- /* invokes function which allocates memory for a final state */
- final = buildstate();
- /* execute code according to the current occurance indicator */
- switch(occind){
- /* if occurance indicator is required ...*/
- case REQ:
- /* set start state to point to final state */
- start -> lptr = final;
- /* and label the edge with the token */
- start -> llabel = token;
- start -> linst = inst;
- /****************************/
- /* A1 ==> A */
- /* [S]----->[F] */
- /****************************/
- break;
- /* if occurance indicator is optional ... */
- case REP:
- case OPT:
- /* set start state to point to final state with one edge */
- start -> lptr = final;
- /* and label the edge with the token */
- start -> llabel = token;
- start -> linst = inst;
- /* also set start state to point to final state with */
- /* another edge */
- start -> rptr = final;
- /* and label the edge with EMPTY */
- start -> rlabel = EMPTY;
- /****************************/
- /* A? ==> A */
- /* [S]=====>[F] */
- /* e */
- /****************************/
- if(occind == OPT)
- break;
- /* Otherwise set final state back to start state */
- final->lptr = start;
- final->llabel = BACK;
- /****************************/
- /* A? ==> A */
- /* [S]=====>[F] */
- /* ^ e | */
- /* | | */
- /* +--------+ */
- /* b */
- /****************************/
- break;
- /* if occurance indicator is required-repeatable... */
- case PLUS:
- /* set start state to point to final state */
- start -> lptr = final;
- /* and label the edge with the token */
- start -> llabel = token;
- start -> linst = inst;
- /* set the final state to point to itself */
- final -> lptr = final;
- /* and label the edge with the token */
- final -> llabel = token;
- final -> linst = inst;
- /****************************/
- /* A+ ==> A */
- /* [S]----->[F]-+ */
- /* ^ |A */
- /* |___| */
- /****************************/
- break;
- }
- /* invoke function which allocates memory for a FSAid */
- startid = buildid();
- /* set "startid" to point to the start state of the FSA just built */
- startid -> startptr = start;
- /* set "startid" to point to the final state of the FSA just built */
- startid -> finalptr = final;
- /****************************/
- /* [ID]--->[S]- ... ->[F] */
- /* | ^ */
- /* |_________________| */
- /****************************/
- /* return the pointer to the FSAid of the FSA just built */
- return(startid);
- }
- /************************************************************************/
- /************************************************************************/
- /* LOWGRP inputs a subgroup of an expression whose tokens have pre- */
- /* viously been "FSAtokened" and processes these FSAtokens with their */
- /* connectors, building an FSA equivalent to the "content" of the */
- /* current subgroup. This procedure then passes this "subgroup"FSA */
- /* along with the occurance indicator on the subgroup to another process*/
- /* which builds an FSA equivalent to the "entire" subgroup, repalcing */
- /* the subgroup with an FSAid pointer pointing to the newly built ,more */
- /* complex, FSA. */
- /************************************************************************/
- void lowgrp(iptr, nest)
- ITEM *iptr;
- int nest;
- {
- int connector,occindongrp;
- STATEID *FSAid;/* the "ultimate" FSAid for the subgroup */
- STATEID *FSAtokid;/* the FSAtokens from the subgroup being */
- /* added to the "ultimate" FSAid for the subgroup */
-
- /* invokes procedure which will strip the GRPO from the subgroup */
- stripunit(INT,iptr);
- /* invokes function which allocates memory for a FSAid */
- FSAid = buildid();
- /* invokes a function to get and strip current /*
- /* FSAtoken from the subgroup */
- FSAtokid = getFSAtoken(iptr);
- /* for the first FSAtoken stripped from the subgroup, */
- /* simply set the "ultimate" FSAid to point to it. */
- /* set FSAid to point to the first FSAtoken's start state */
- FSAid -> startptr = FSAtokid -> startptr;
- /* and set FSAid to plint to the first FSAtoken's final state */
- FSAid -> finalptr = FSAtokid -> finalptr;
- free((char *)FSAtokid);
- /* while not end of subgroup... */
- while((connector = getconnector(iptr)) != GRPC){
- /* invokes a function to get and strip current connector from subgroup */
- /* invokes a function to get and strip next FSAtoken from subgroup */
- FSAtokid = getFSAtoken(iptr);
- /* invokes a function to build a new "ultimate" FSAid, returning */
- /* a FSAid pointer pointing to the newly built "unltimate" FSA. */
- FSAid = FSAgrp(FSAid,connector,FSAtokid);
- }
- /* if level of nesting > 1, then the occurance indicator along with */
- /* the "ultimate" FSA just built for the current subgroup must be */
- /* processed */
- /* INTERESTING */
- if(nest >= 1){
- /* invokes a function to get and strip the occurance indicator off */
- /* of the current subgroup */
- occindongrp = getoccind(iptr);
- /* invokes a function taking the "ultimate" FSA and the occurance */
- /* indicator from the current subgroup and building an equivalent */
- /* new ultimate FSA for the "entire" subgroup, returning the FSAid*/
- /* pointer pointing to the new, more complex, FSA */
- FSAid = FSAgrpocid(FSAid,occindongrp);
- }
- /* invoke a procedure to insert the newly built "ultimate" FSAid */
- /* pointer into the expression where the current subgroup was located*/
- insertpointer(&iptr,FSAid);
- /* exit this procedure after entire subgroup has been processed and */
- /* replaced by an equivalent FSAid pointer */
- }
- /************************************************************************/
- /************************************************************************/
- /* GETFSATOKEN gets the FSAtoken pointed to by "iptr", strips the space */
- /* taken by the FSAtoken from the expression, and returns the FSAtoken */
- /************************************************************************/
- STATEID *getFSAtoken(iptr)
- ITEM *iptr;
- {
- STATEID *stateid;/* will contain the FSAtoken */
-
- /* if "iptr" does not point to a FSAid, then execution error */
- /* in constructive algorithm */
- if(iptr->itoken != POINTER)
- myexit(1,"FSA token id ponter not found");
- /* invoke procedure to strip the, -1, signalling a pointer */
- /* from the expression at "iptr" */
- stripunit(INT,iptr);
- /* set "stateid" to the current FSAtoken pointed to */
- stateid = iptr->ptoken;
- /* invoke procedure to strip the current FSAtoken from the expression */
- stripunit(PTR,iptr);
- /* return "stateid" which was assigned FSAtoken */
- return(stateid);
- }
- /************************************************************************/
- /************************************************************************/
- /* FSAGRP inputs the most recent "ultimate" FSAid and (connector,FSAid) */
- /* pair, building a new, more complex, "ultimate" FSA, returning the */
- /* FSAid pointing to the "new" ultimate FSA. */
- /************************************************************************/
- STATEID *FSAgrp(FSAid,connector,FSAtokid)
- STATEID *FSAid,*FSAtokid;
- int connector;
- {
- STATE *newstart, *newfinal;/* new start and final states */
- /* of new "ultimate" FSA being built */
- STATEID *newstartid;/* new FSAid to point to FSA being built */
-
- switch(connector){
- /* if connector is the sequence operator ... */
- case SEQ:
- /* if the "ultimate" FSA's final state's left pointer is NULL ...*/
- if((FSAid->finalptr->lptr) == NULL){
- /* then the left pointer is set to point to the start */
- /* state of the FSAtokid */
- FSAid->finalptr->lptr = FSAtokid -> startptr;
- /* and the edge is marked EMPTY */
- FSAid->finalptr->llabel = EMPTY;
- }
- /* otherwise the left pointer of the "ultimate" FSA's final state */
- /* is assigned to something valid */
- else{
- /* so check the right pointer of the "ultimate FSA's final */
- /* and if not NULL ... */
- if((FSAid->finalptr->rptr) == NULL){
- /* then the right pointer is set to point to the start */
- /* state of the FSAtokid */
- FSAid->finalptr->rptr = FSAtokid -> startptr;
- /* and the edge is marked EMPTY */
- FSAid->finalptr->rlabel = EMPTY;
- }
- /* otherwise the final state of the "utimate" FSA is full */
- /* which means an error occurred in the constructive algorithm */
- else
- myexit(1,"no null ptr found in state");
- }
- /*********************************/
- /* [FSAid]---->[S]- ... ->[F]--+ */
- /* | ^ | */
- /* |____________________| e| */
- /* +-----------+ */
- /* | */
- /* V */
- /* [FSAtokid]---->[S]- ... ->[F] */
- /* | ^ */
- /* |_______________________| */
- /*********************************/
-
- /* set the "ultimate" FSAid to point to the finalstate of */
- /* the FSAtokid */
- FSAid->finalptr = FSAtokid->finalptr;
- /* release the memory of the FSAtokid */
- free((char *)FSAtokid);
- /***********************************/
- /* [FSAid]---->[S]- ... ->[F]--+ */
- /* | | */
- /* | e | */
- /* +--+ +---------+ */
- /* | | */
- /* | V */
- /* | [FSAtokid]-|| [S]- ... ->[F] */
- /* | | ^ */
- /* | = | */
- /* +----------------------------+ */
- /***********************************/
- /* return the "new" ultimate FSAid */
- return(FSAid);
- /* if connector is the OR operator ...*/
- case OR:
- /* allocate memory for a new start state */
- newstart = buildstate();
- /* allocate memory for a new final state */
- newfinal = buildstate();
- /* allocate memory for a new FSAid */
- newstartid = buildid();
- /* set new FSAid to point to new start state */
- newstartid->startptr = newstart;
- /* set new FSAid to point to new final state */
- newstartid->finalptr = newfinal;
- /* set new start state to point to start state of "ultimate" FSA */
- newstart->lptr = FSAid->startptr;
- /* mark the edge EMPTY */
- newstart->llabel = EMPTY;
- /* set new start state to point to start state of FSAtokid */
- newstart->rptr = FSAtokid->startptr;
- /* mark the edge EMPTY */
- newstart->rlabel = EMPTY;
- /*************************************************************/
- /* +---------------+ */
- /* | | */
- /* | V */
- /* e| [FSAid]---->[S]- ... ->[F] */
- /* | | ^ */
- /* | |____________________| */
- /* [newstartid]--->[newstart]=+----------------+ */
- /* | e | */
- /* | V */
- /* V [FSAtokid]---->[S]- ... ->[F] */
- /* [newfinal] | ^ */
- /* |_______________________| */
- /*************************************************************/
- /* if left pointer of "ultimate" FSA's final state is NULL ..*/
- if((FSAid->finalptr->lptr) == NULL){
- /* set FSAid to point to the new final state */
- FSAid->finalptr->lptr = newfinal;
- /* and mark the edge as EMPTY */
- FSAid->finalptr->llabel = EMPTY;
- }
- /* otherwise the left pointer of the "ultimate" FSA's final state */
- /* is assigned valid data */
- else{
- /* if right pointer of "ultimate" FSA's final state is NULL ..*/
- if((FSAid->finalptr->rptr) == NULL){
- /* set FSAid to point to the new final state */
- FSAid->finalptr->rptr = newfinal;
- /* and mark the edge as EMPTY */
- FSAid->finalptr->rlabel = EMPTY;
- }
- else
- /* otherwise the final state of "ultimate" FSA is full */
- /* implying that an error has occurred in the constructive */
- /* algotithm */
- myexit(1,"no null ptr found in state");
- }
- /* if left pointer of FSAtokid's final state pointer is NULL ...*/
- if((FSAtokid->finalptr->lptr) == NULL){
- /* set FSAtoken's final state to the new final state */
- FSAtokid->finalptr->lptr = newfinal;
- /* and mark the edge as EMPTY */
- FSAtokid->finalptr->llabel = EMPTY;
- }
- /* otherwise the left pointer is already assigned */
- else{
- /* if right pointer of FSAtokid's final state pointer is NULL ...*/
- if((FSAtokid->finalptr->rptr) == NULL){
- /* set FSAtoken's final state to the new final state */
- FSAtokid->finalptr->rptr = newfinal;
- /* and mark the edge as EMPTY */
- FSAtokid->finalptr->rlabel = EMPTY;
- }
- else
- /* otherwise FSAtokid's final state is full implying an */
- /* error has occurred in the constructive algorithm */
- myexit(1,"no null ptr found in state");
- }
- /* release the memory of the "old" ultimate FSAid */
- free((char *)FSAid); /* we took cast out */
- /* release the memory of the FSAtoken's id */
- free((char *)FSAtokid); /* we took cast out */
- /*********************************************************************/
- /* +-----------------+ */
- /* [newstartid] | | */
- /* | | | V */
- /* | | e| [FSAid]-|| [S]- ... ->[F]---+ */
- /* | | | | |e */
- /* | | | = V */
- /* | +->[newstart] [newfinal] */
- /* | | = ^ ^ */
- /* | e| | |e | */
- /* | | [FSAtokid]-|| [S]- ... ->[F]-+ | */
- /* | | ^ | */
- /* | |___________________| | */
- /* |_____________________________________________________| */
- /*********************************************************************/
- /* return newstartid to become the new "ultimate" FSAid */
- return(newstartid);
- }
- return(0);
- }
- /************************************************************************/
- /************************************************************************/
- /* FSAGRPOCID inputs an equivalent FSA of a subgroup and the occurance */
- /* indicator on that group and forms a new FSA for that "entire" sub- */
- /* group, returning a FSAid for the new, more complex, FSA. */
- /************************************************************************/
- STATEID *FSAgrpocid(FSAid,occindongrp)
- STATEID *FSAid;
- int occindongrp;
- {
- STATEID *newstartid;/* new FSAid, to be used if, optional, */
- /* occurance indicator */
- STATE *newstart;/* new start state for FSA being built */
- /* if occurance indicator is ,optional */
-
- STATE *newfinal;/* new final state for FSA being built */
- /* if occurance indicator is required/repeatable */
-
- switch(occindongrp){
- /* if occurance indicator on the group is required ...*/
- case(REQ):
- /* simply return, no changes to current FSA is needed */
- return(FSAid);
- /* if occurance indicator on the group is required-repeatable ...*/
- case(PLUS):
- /* allocate new final state if plus */
- newfinal = buildstate();
- /* set newfinal to point to FSA's start state */
- newfinal->lptr = FSAid->startptr;
- /* and mark the edge as BACK */
- newfinal->llabel = BACK;
- /* if the FSA's final state's left pointer is NULL ...*/
- if((FSAid->finalptr->lptr) == NULL){
- /* set FSA's final state to point to new final state */
- FSAid->finalptr->lptr = newfinal;
- /* and mark the edge as EMPTY */
- FSAid->finalptr->llabel = EMPTY;
- /* update FSAid's finalptr to point to new final state */
- FSAid->finalptr = newfinal;
- }
- /* otherwise the left pointer of the final state has already */
- /* been assigned */
- else{
- /* if the FSA's final state's right pointer is NULL ...*/
- if((FSAid->finalptr->rptr) == NULL){
- /* set FSA's final state to point to new final state */
- FSAid->finalptr->rptr = newfinal;
- /* and mark the edge as EMPTY */
- FSAid->finalptr->rlabel = EMPTY;
- /* update FSAid's finalptr to point to new final state */
- FSAid->finalptr = newfinal;
- }
- else
- /* otherwise an error has occurred in the constructive */
- /* algorithm because the final state is full */
- myexit(1,"no null ptr found in state");
- }
- /*******************************/
- /* __________ */
- /* | b | */
- /* V | */
- /* [FSAid]--->[S]- ... ->[F] */
- /* | ^ */
- /* |__________________| */
- /*******************************/
- /* return the FSAid of the old FSA as the new FSAid */
- return(FSAid);
- /* if occurance indicator on the group is optional .. */
- case(REP):
- case(OPT):
- /* allocate memory for a new FSAid */
- newstartid = buildid();
- /* allocate memory for a new start state */
- newstart = buildstate();
- /* allocate memory for a new final state */
- newfinal = buildstate();
- /* set the new FSAid to point to the new start state */
- newstartid->startptr = newstart;
-
- /* set the new FSAid to point to the new final state */
- newstartid->finalptr = newfinal;
-
- /* set the new start state to point to the start state of the */
- /* current FSA */
- newstart->lptr = FSAid->startptr;
- /* and mark the edge as EMPTY */
- newstart->llabel = EMPTY;
-
- /* set the new start state to point to the new final state */
- newstart->rptr = newfinal;
- newstart->rlabel = EMPTY;
-
- /* set old final state to point to the new final state */
- if(FSAid->finalptr->lptr == NULL){
- FSAid->finalptr->lptr = newfinal;
- /* set old final state's left pointer to EMPTY */
- FSAid->finalptr->llabel = EMPTY;
- }
- else{
- if(FSAid->finalptr->rptr == NULL){
- FSAid->finalptr->rptr = newfinal;
- FSAid->finalptr->rlabel = EMPTY;
- }
- else{
- fprintf(stderr,"State pointer overflow occurred\n");
- exit(1);
- }
- }
- /* release the memory of the old FSAid */
- free((char *)FSAid); /* we took cast out */
-
- /*******************************************************/
- /* +---------------+ */
- /* [newstartid] e| | */
- /* | | | V */
- /* | +--->[newstart] [FSAid]-|| [S]- ... ->[F] */
- /* | | | ^ ^ */
- /* | e| = | | */
- /* | +-------------------------+ | */
- /* |____________________________________________| */
- /*******************************************************/
- /* return the new FSAid to replace the old FSAid */
- if(occindongrp == OPT)
- return(newstartid);
- /* Otherwise set newfinal state to point to new start state */
- newfinal->lptr = newstart;
- newfinal->llabel = BACK;
- return(newstartid);
- }
- /* code should never be reached, but if so, then an error in */
- /* the constructive algorithm */
- return(0);
- }
-